
require 'appwiki/user/user.rb'
require_gem 'acts_as_taggable'

# a map of users who belong to this group
class GroupsUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :group
end

# groups
class Group < ActiveRecord::Base

    acts_as_taggable

    belongs_to :user
    has_many :groups_users, :dependent => true
    has_many :users, :through => :groups_users

    validates_length_of :uid, :within => 3..64

    validates_format_of :uid,
                        :with => /^([a-z0-9_]+){0,2}[a-z0-9_]+$/i,
                        :on => :create,
                        :message => "can only contain letters and digits"

    ########################################################
    # misc
    ########################################################

    def is_a_member?(user)
      if GroupsUser.find(:first, :conditions => ["user_id = ? and group_id = ?",user.id,self.id ] )
        return true
      end
      return false
    end

    def join(user,role=nil)
      if !is_a_member?(user)
        begin
          x = GroupsUser.new(:user_id => user.id, :group_id => self.id )
          x.role = role if role && role.length > 0
          x.save
        rescue
          return false
        end
      end
      return true
    end

    def leave(user)
      if is_a_member?(user)
        begin
          GroupsUser.find_by_sql("DELETE FROM groups_users WHERE group_id = #{self.id} and user_id = #{user.id}")
        rescue
          return false
        end
      end
      return true
    end

    def Group.get_memberships(user)
      # get groups this user is watching
      res = Array.new
      results = GroupsUser.find(:all, :conditions => ["user_id = ?",user.id], :order => "id DESC", :offset => 0, :limit => 99)
      results.each do |result|
        group = Group.find_by_id(result.group_id)
        res << group if group
      end
      return res
    end

    def get_members()
      # get members of this group
      res = Array.new
      results = GroupsUser.find(:all, :conditions => ["group_id = ?",self.id], :order => "id DESC", :offset => 0, :limit => 99)
      results.each do |result|
        user = User.find_by_id(result.user_id)
        res << user if user
      end
      return res
    end

    def get_sponsor()
      user = User.find_by_id(self.sponsor)
      if !user
        user = User.new
        user.login = "anonymous"
      end
      return user
    end

    ########################################################
    # misc
    ########################################################

    def set(params)

      # set parameters [ sadly bypasses validation xxx ]
      params.each { |x,y| self.send(x.to_s+'=',y) if self.has_attribute?(x) }

      # validate
      self.valid?

    end

    def save

      # finalize it
      state = super

      # if succeeded then apply tags - it should have succeeded
      if state
        if self.id && self.tagstring
          Group.find_by_sql("DELETE FROM groups_tags WHERE group_id = #{self.id}")
          self.tag self.tagstring
        end
      end

      return state
    end

  protected

    ##########################################################################
    # schema
    # xxx should just extend notes - it is a clone of notes
    ##########################################################################

    def self.schema
      self.schema_001
    end

    def self.schema_drop
      return if !table_exists?
      ActiveRecord::Schema.define do
        drop_table :groups_tags
        drop_table :groups_users
        drop_table :groups
      end
    end

    def self.schema_001
      return if table_exists?
      ActiveRecord::Schema.define do
        begin
          create_table :tags do |t|
            # t.column :id,              :serial, :null => false
            t.column :name,            :text
          end
        rescue
        end
        begin
          create_table :groups_tags do |t|
            t.column :tag_id,          :integer, :null => false
            t.column :group_id,        :integer, :null => false
          end
          remove_column :groups_tags, :id
        rescue
        end
        begin
          create_table :groups_users do |t|
            t.column :user_id,         :integer, :null => false
            t.column :group_id,        :integer, :null => false
            t.column :role,            :text
          end
        rescue
        end
        begin
          create_table :groups do |t|
            #t.column :id,              :serial, :null => false
            t.column :uid,             :text
            t.column :parent,          :integer
            t.column :handler,         :text
            #t.column :type,            :text
  
            t.column :title,           :text
            t.column :link,            :text
            t.column :description,     :text
            t.column :tagstring,       :text
            t.column :depiction,       :text
            t.column :extended,        :text
  
            t.column :sponsor,         :integer
            t.column :perms,           :integer
            t.column :nchildren,       :integer
            t.column :nobservers,      :integer
            t.column :location,        :text
            t.column :lat,             :float
            t.column :lon,             :float
            t.column :begins,          :datetime
            t.column :ends,            :datetime
            t.column :created_at,      :datetime
            t.column :modified_at,     :datetime

            # group properties  
            t.column :email,           :string , :limit => 90, :null => false, :default => ''
            t.column :websites,        :text
            t.column :openid_url,      :text
            t.column :verified,        :integer, :default => 0
            t.column :role,            :string , :limit => 40, :default => ''

          end
        rescue
        end
      end
    end
  end

Group.schema
